﻿--[[--
	ALA@163UI
--]]--
--[[
	ALASCR = ScrollList.CreateScrollFrame
	scroll = ALASCR(parent, width, height, buttonHeight, funcToCreateButton(parent: ScrollFrame.ScrollChild, index, buttonHeight), functToSetButton(button, data_index))
	scroll:SetNumValue(num)
	scroll:HandleButtonByDataIndex(index, func, ...)			func(button, ...)
	scroll:HandleButtonByRawIndex(index, func, ...)				func(button, ...)
	scroll:CallButtonFuncByRawIndex(index, FuncName, ...)		button:func(...)
	scroll:CallButtonFuncByDataIndex(index, FuncName, ...)		button:func(...)
	button:GetDataIndex()
]]
local __version = 4;

local _G = _G;
_G.__ala_meta__ = _G.__ala_meta__ or {  };
local __ala_meta__ = _G.__ala_meta__;

-->			versioncheck
	local ScrollList = _G.alaScrollList;
	if ScrollList ~= nil and ScrollList.__minor ~= nil and ScrollList.__minor >= __version then
		return;
	end
	ScrollList = ScrollList or {  };
	ScrollList.__minor = __version;
	ScrollList._Created = ScrollList._Created or {  };
-->

-->			upvalue
	local ceil, floor, max, min = ceil, floor, max, min;
	local _ = nil;

	local function _error_(key, msg, ...)
		print("\124cffff0000" .. key .. "\124r", msg and "\124cffff0000" .. msg .. "\124r", ...);
	end

-->			constant
	local def_inner_size = 64;

-->
	function ScrollList.CreateScrollFrame(parent, width, height, buttonHeight, funcToCreateButton, functToSetButton)
		width = width and max(width, def_inner_size) or def_inner_size;
		height = height and max(height, def_inner_size) or def_inner_size;

		local scrollFrame = CreateFrame("SCROLLFRAME", nil, parent);
		local scrollChild = CreateFrame("FRAME", nil, scrollFrame);
		local scrollBar = CreateFrame("SLIDER", nil, scrollFrame);
		local buttons = {};
		local nButtonsShown = 0;
		local ofsIndex = 0;
		local numValue = -1;

		local sbWidth = 20;

		scrollFrame:Show();
		scrollFrame:EnableMouse(true);
		scrollFrame:SetMovable(true);
		scrollFrame:RegisterForDrag("LeftButton");
		scrollFrame:SetVerticalScroll(0);
		scrollFrame:SetScrollChild(scrollChild);
		scrollFrame:SetScript("OnMouseWheel", function(self, delta, stepSize)
			stepSize = stepSize or buttonHeight;
			local minVal, maxVal = scrollBar:GetMinMaxValues();
			scrollBar:SetValue(min(maxVal, max(minVal, scrollBar:GetValue() - delta * stepSize)));
		end);
		function scrollFrame:OnSizeChanged(width, height)
			-- width = width or scrollFrame:GetWidth();
			height = height or scrollFrame:GetHeight();
			scrollChild:SetHeight(height);
			--scrollBar:SetValue(mscrollBar:GetValue());
			scrollChild:CreateScrollChildButtons();
			scrollFrame:Update();
		end
		function scrollFrame:SetButtonHeight(height)
			if buttonHeight == height then
				return;
			end
			buttonHeight = height;
			scrollFrame:OnSizeChanged();
		end
		-- scrollFrame._SetSize = scrollFrame.SetSize;
		-- function scrollFrame:SetSize(...)
		-- 	scrollFrame:_SetSize(...);
		-- 	scrollFrame:OnSizeChanged(...);
		-- end
		-- scrollFrame._SetHeight = scrollFrame.SetHeight;
		-- function scrollFrame:SetHeight(...)
		-- 	scrollFrame:_SetHeight(...);
		-- 	scrollFrame:OnSizeChange(scrollFrame:GetWidth(), ...);
		-- end
		-- scrollFrame._SetWidth = scrollFrame.SetWidth;
		-- function scrollFrame:SetWidth(...)
		-- 	scrollFrame:_SetWidth(...);
		-- 	scrollChild:SetWidth(...);
		-- end
		scrollFrame:SetScript("OnSizeChanged", scrollFrame.OnSizeChanged);
		scrollFrame:SetScript("OnDragStart", function(self, button)
				if parent:IsMovable() then
					parent:StartMoving();
				end
			end
		);
		scrollFrame:SetScript("OnDragStop", function(self, button)
				parent:StopMovingOrSizing();
			end
		);
		scrollFrame:SetScript("OnShow", function(self)
			scrollFrame:Update();
		end);
		function scrollFrame:UpdateButtons()
			if scrollFrame:IsVisible() then
				for i = 1, nButtonsShown do
					functToSetButton(buttons[i], i + ofsIndex);
				end
			end
		end
		function scrollFrame:Update()
			if scrollFrame:IsVisible() then
				local maxVal = max(numValue - nButtonsShown + 2, 0) * buttonHeight;
				local val = min(scrollBar:GetValue(), maxVal);
				scrollBar:SetMinMaxValues(0, maxVal);
				scrollBar:SetValue(val);
				if nButtonsShown - 1 > numValue then
					scrollBar:Hide();
					scrollChild:SetWidth(scrollFrame:GetWidth());
				else
					scrollBar:Show();
					scrollChild:SetWidth(scrollFrame:GetWidth() - sbWidth);
				end
				scrollFrame:UpdateButtons();
			end
		end
		function scrollFrame:SetNumValue(n)
			if n >= 0 and numValue ~= n then
				numValue = n;
				scrollFrame:Update();
			end
		end
		function scrollFrame:HandleButtonByDataIndex(index, func, ...)
			return scrollFrame:HandleButtonByRawIndex(index - ofsIndex, func, ...);
		end
		function scrollFrame:HandleButtonByRawIndex(index, func, ...)
			if index >= 1 and index <= #buttons then
				return func(buttons[index], ...);
			else
				-- _error_("HandleButtonByRawIndex", index);
				return nil;
			end
		end
		function scrollFrame:CallButtonFuncByRawIndex(index, func, ...)
			if index >= 1 and index <= #buttons then
				func = buttons[index][func];
				if func then
					return func(buttons[index], ...);
				else
					_error_("CallButtonFuncByRawIndex", index);
					return nil;
				end
			else
				-- _error_("CallButtonFuncByRawIndex", index);
				return nil;
			end
			return nil;
		end
		function scrollFrame:CallButtonFuncByDataIndex(index, func, ...)
			return scrollFrame:CallButtonFuncByRawIndex(index - ofsIndex, func, ...);
		end


		scrollChild:Show();
		scrollChild:SetPoint("LEFT", scrollFrame);
		local function GetDataIndex(self)
			return self.id + ofsIndex;
		end
		function scrollChild:CreateScrollChildButtons()
			local num = ceil(scrollChild:GetHeight() / buttonHeight) + 1;
			if num == nButtonsShown then
				return;
			end
			if not buttons[1] then
				local button = funcToCreateButton(scrollChild, 1, buttonHeight);
				button.id = 1;
				buttons[1] = button;
				button:SetPoint("TOPLEFT");
				button:SetPoint("TOPRIGHT");
				button:Show();
				nButtonsShown = 1;
				button.GetDataIndex = GetDataIndex;
			end
			if num < nButtonsShown then
				for i = num + 1, nButtonsShown do
					buttons[i]:Hide();
				end
			else
				for i = nButtonsShown + 1, num do
					local button = funcToCreateButton(scrollChild, i, buttonHeight);
					button.id = i;
					buttons[i] = button;
					button:SetPoint("TOPLEFT", buttons[i - 1], "BOTTOMLEFT", 0, 0);
					button:SetPoint("TOPRIGHT", buttons[i - 1], "BOTTOMRIGHT", 0, 0);
					buttons[i]:Show();
					button.GetDataIndex = GetDataIndex;
				end
			end
			nButtonsShown = num;
			--scrollChild:SetHeight(buttonHeight * nButtonsShown);
			scrollBar:SetStepsPerPage(nButtonsShown - 2);
		end


		scrollBar:SetWidth(sbWidth);
		scrollBar:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", 0, 0);
		scrollBar:SetPoint("BOTTOMRIGHT", scrollFrame, "BOTTOMRIGHT", 0, 0);
		scrollBar:Show();
		scrollBar:EnableMouse(true);
		scrollBar:SetValueStep(buttonHeight);
		scrollBar:SetMinMaxValues(0, 0);
		scrollBar:SetValue(0);
		-- local top = scrollBar:CreateTexture(nil, "ARTWORK");
		-- top:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar");
		-- top:SetSize(27, 24);
		-- top:SetTexCoord(0.0, 0.484375, 0.0, 0.10);
		-- top:SetPoint("TOPLEFT", -4, 17);
		-- local bot = scrollBar:CreateTexture(nil, "ARTWORK");
		-- bot:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar");
		-- bot:SetSize(27, 24);
		-- bot:SetTexCoord(0.515625, 1.0, 0.3140625, 0.4140625);
		-- bot:SetPoint("BOTTOMLEFT", -4, -15);
		-- local mid = scrollBar:CreateTexture(nil, "ARTWORK");
		-- mid:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar");
		-- mid:SetTexCoord(0.0, 0.484375, 0.1640625, 1.0);
		-- mid:SetPoint("TOPLEFT", top, "BOTTOMLEFT", 0, 0);
		-- mid:SetPoint("BOTTOMRIGHT", bot, "TOPRIGHT", 0, 0);
		do
			local left = scrollBar:CreateTexture(nil, "ARTWORK");
			left:SetWidth(2);
			left:SetPoint("TOPLEFT");
			left:SetPoint("BOTTOMLEFT");
			left:SetColorTexture(0.0, 0.0, 0.0, 1.0);
			local right = scrollBar:CreateTexture(nil, "ARTWORK");
			right:SetWidth(2);
			right:SetPoint("TOPRIGHT");
			right:SetPoint("BOTTOMRIGHT");
			right:SetColorTexture(0.0, 0.0, 0.0, 1.0);
			local top = scrollBar:CreateTexture(nil, "ARTWORK");
			top:SetHeight(2);
			top:SetPoint("TOPLEFT");
			top:SetPoint("TOPRIGHT");
			top:SetColorTexture(0.0, 0.0, 0.0, 1.0);
			local bot = scrollBar:CreateTexture(nil, "ARTWORK");
			bot:SetHeight(2);
			bot:SetPoint("BOTTOMLEFT");
			bot:SetPoint("BOTTOMRIGHT");
			bot:SetColorTexture(0.0, 0.0, 0.0, 1.0);
		end
		scrollBar:SetThumbTexture("Interface\\Buttons\\UI-ScrollBar-Knob");
		local thumb = scrollBar:GetThumbTexture();
		thumb:SetSize(sbWidth - 2, 24);
		thumb:SetTexCoord(0.20, 0.80, 0.125, 0.875);
		thumb:SetColorTexture(0.25, 0.25, 0.25, 1.0);

		scrollBar:SetScript("OnValueChanged", function(self, value)
			value = value or scrollBar:GetValue();
			local index = value / buttonHeight;
			local ofs = (index - floor(index)) * buttonHeight;
			scrollFrame:SetVerticalScroll(ofs);
			ofsIndex = floor(index);
			scrollFrame:UpdateButtons();
		end);

		function scrollFrame:SetBarWidth(w)
			sbWidth = w;
			scrollBar:SetWidth(sbWidth);
			thumb:SetSize(sbWidth - 2, 24);
			scrollFrame:Update();
		end

		if width and height then
			scrollFrame:SetSize(width, height);
		end

		scrollFrame:SetNumValue(0);

		ScrollList._Created[scrollFrame] = __version;

		return scrollFrame;
	end

-->

_G.alaScrollList = ScrollList;
_G["ALASCR"] = ScrollList.CreateScrollFrame;

